package jdbc;

import org.junit.jupiter.api.Test;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * 批处理
 */
public class Batch_ {

    public static void main(String[] args) {

        /*
            1.当需要成批插入或者更新记录时。可以采用java的批量更新机制，这一机制允许多条语句一次性提交给数据库批量处理
            2.JDBC的批处理语句包括以下方法：
                1. addBatch() 添加需要批量处理的SQL语句
                2. executeBatch() 执行批量处理语句
                3. clearBatch() 清空批处理包的语句
            3.JDBC连接Mysql时，如果要使用批处理功能，在url中加入参数
                ?rewriteBatchedStatements = true
            4.批处理往往和PreparedStatement一起搭配使用，可以减少编译次数和运行次数，提高效率
         */

        /*
            演示向admin2表中添加5000条数据，看看批处理耗时多久
            需要修改配置文件 jdbc.properties url=jdbc:mysql://localhost:3306/数据库?rewriteBatchedStatements=true
         */
    }

    @Test
    public void noBatch() throws Exception {
        Connection connection = JDBCUtils.getConnection();
        String sql = "insert into admin2 values (null, ?, ?)";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        System.out.println("开始执行...");
        long start = System.currentTimeMillis();
        for (int i = 0; i < 5000; i++) {
            preparedStatement.setString(1, "jack" + i);
            preparedStatement.setString(2, "666");
            preparedStatement.executeUpdate();
        }
        long end = System.currentTimeMillis();
        System.out.println("执行完毕，耗时：" + (end - start) + "ms");//传统耗时10702
        //关闭连接
        JDBCUtils.close(null, preparedStatement, connection);
    }

    @Test
    public void batch() throws Exception {
        Connection connection = JDBCUtils.getConnection();
        String sql = "insert into admin2 values (null, ?, ?)";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        System.out.println("开始执行...");
        long start = System.currentTimeMillis();
        for (int i = 0; i < 5000; i++) {
            preparedStatement.setString(1, "jack" + i);
            preparedStatement.setString(2, "666");
            //将sql 语句加入到批处理包 -> 看源码
            /*
                public void addBatch(Object batch) {
                    if (this.batchedArgs == null) {
                        //1.第一步就创建ArrayList - elementData对象数组
                        //2.elementData对象数组存放预处理 sql语句
                        //3.当elementData满后，就按照1.5倍扩容
                        //4.当添加到指定之后，就执行 executeBatch
                        //5.批量处理会减少发送sql语句的网络开销，减少编译次数，效率提高
                        this.batchedArgs = new ArrayList();
                    }

                    this.batchedArgs.add(batch);
                }
             */
            preparedStatement.addBatch();
            //当有1000条记录时，再批量执行
            if ((i + 1) % 1000 == 0) {
                preparedStatement.executeBatch();
                //清空批处理包
                preparedStatement.clearBatch();
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("批处理执行完毕，耗时：" + (end - start) + "ms");//批处理耗时90ms
        //关闭连接
        JDBCUtils.close(null, preparedStatement, connection);
    }
}
